/*
 * ImPduBase.h
 *
 *  Created on: 2013-8-27
 *      Author: ziteng@mogujie.com
 */

#ifndef IMPDUBASE_H_
#define IMPDUBASE_H_
#include "UtilPdu.h"
#include <sstream>

#define IM_PDU_HEADER_LEN		8

/* added by luoning 2014.06.10. */
/* added end */

#define PARSE_PACKET_ASSERT if (is.GetPos() != (nLen - IM_PDU_HEADER_LEN)) { \
        ostringstream ostr;\
        ostr << "parse packet failed, ";\
        string reason = ostr.str();\
		throw CPduException(m_pdu_header.command_id, ERROR_CODE_PARSE_FAILED, reason.c_str()); \
	}

#define ALLOC_FAIL_ASSERT(p) if (p == NULL) { \
		throw CPduException(m_pdu_header.command_id, ERROR_CODE_ALLOC_FAILED, "allocate failed"); \
	}


//////////////////////////////
typedef struct {
	uint32_t 	length;		// 数据包长度，包括包头
	uint16_t	command_id;	// 命令号
    uint16_t	reserved;	// 保留，可用户如序列号等
} PduHeader_t;


class CImPdu
{
public:
	CImPdu();
	virtual ~CImPdu() {}

	uchar_t* GetBuffer();
	uint32_t GetLength();

	uint16_t GetCommandId() { return m_pdu_header.command_id; }
    uint16_t GetReserved() { return m_pdu_header.reserved; }

	void SetReserved(uint16_t reserved);

	void WriteHeader();
	virtual uint16_t GetPduType() { return 0; }

	static bool IsPduAvailable(uchar_t* buf, uint32_t len, uint32_t& pdu_len);
	static int ReadPduHeader(uchar_t* buf, uint32_t len, PduHeader_t* header);
	static CImPdu* ReadPdu(uchar_t* buf, uint32_t len);
private:

	void _SetIncomingLen(uint32_t len) { m_incoming_len = len; }
	void _SetIncomingBuf(uchar_t* buf) { m_incoming_buf = buf; }

protected:
	CSimpleBuffer	m_buf;
	uchar_t*		m_incoming_buf;
	uint32_t		m_incoming_len;
	PduHeader_t		m_pdu_header;
};

#endif /* IMPDUBASE_H_ */
